package com.mxpio.erp.oa.service.impl;

import com.google.common.collect.Lists;
import com.mxpio.erp.common.enums.BizExceptionEnums;
import com.mxpio.erp.common.enums.OrderStatusEnums;
import com.mxpio.erp.common.model.request.BpmnSubmitRequest;
import com.mxpio.erp.common.oa.entity.OaBusinessTripApply;
import com.mxpio.erp.common.oa.entity.OaBusinessTripApplyLine;
import com.mxpio.erp.common.oa.service.OaBusinessTripApplyService;
import com.mxpio.erp.common.util.AssertUtil;
import com.mxpio.erp.common.util.CloneUtil;
import com.mxpio.erp.common.util.JacksonMapUtils;
import com.mxpioframework.camunda.service.BpmnFlowService;
import com.mxpioframework.common.exception.MBootException;
import com.mxpioframework.common.vo.Result;
import com.mxpioframework.jpa.JpaUtil;
import com.mxpioframework.jpa.policy.CrudContext;
import com.mxpioframework.jpa.policy.impl.SmartCrudPolicyAdapter;
import com.mxpioframework.security.util.SecurityUtils;
import com.mxpioframework.system.service.PojoDictParseService;
import com.mxpioframework.system.service.impl.BaseServiceImpl;
import org.camunda.bpm.engine.runtime.ProcessInstance;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

;

@Service
public class OaBusinessTripApplyServiceImpl extends BaseServiceImpl<OaBusinessTripApply> implements OaBusinessTripApplyService {

        @Resource
        private BpmnFlowService bpmnFlowService;

        @Resource
        private PojoDictParseService dictService;

        @Override
        @Transactional(rollbackFor = Exception.class)
        public OaBusinessTripApply doSave(OaBusinessTripApply oaBusinessTripApply) {
            oaBusinessTripApply.setBpmnStatus(OrderStatusEnums.BpmnStatus.CREATE.getStatusCode());
            this.save(oaBusinessTripApply, new SmartCrudPolicyAdapter(){
                @Override
                public boolean beforeInsert(CrudContext context) {
                    Object entity = context.getEntity();
                    if(entity instanceof OaBusinessTripApplyLine){
                        OaBusinessTripApply parent = context.getParent();
                        ((OaBusinessTripApplyLine) entity).setBizNo(parent.getBizNo());
                    }
                    return true;
                }
            });
            return oaBusinessTripApply;
        }

        @Override
        @Transactional
        public OaBusinessTripApply submit(BpmnSubmitRequest request) {

            AssertUtil.notEmpty(request.getBizNo(), BizExceptionEnums.PARAM_NOT_NULL, "bizNo");

            OaBusinessTripApply oaBusinessTripApplyOrder = JpaUtil.linq(OaBusinessTripApply.class).collect("bizNo", OaBusinessTripApplyLine.class, "bizNo").equal("bizNo", request.getBizNo()).findOne();
            AssertUtil.notNull(oaBusinessTripApplyOrder, BizExceptionEnums.ORDER_NOT_FOUND);

            if (!oaBusinessTripApplyOrder.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.CREATE.getStatusCode())){
                throw new MBootException("非开立状态，无法重复提交！");
            }
            //1. 开启工作流
            OaBusinessTripApply oaBusinessTripApply = parseDict(oaBusinessTripApplyOrder);
            Map<String, Object> workFlowParam = JacksonMapUtils.convertObjectToMap(oaBusinessTripApply);
            ProcessInstance processInstance = bpmnFlowService.startWithFormByKey(request.getKey(), SecurityUtils.getLoginUsername(), request.getBusinessKey(),workFlowParam);
            //2. 更新工单
            oaBusinessTripApplyOrder.setBpmnStatus(OrderStatusEnums.BpmnStatus.AUDITING.getStatusCode());
            oaBusinessTripApplyOrder.setProcessInstanceId(processInstance.getId());
            this.update(oaBusinessTripApplyOrder);

            return oaBusinessTripApplyOrder;
        }

        @Override
        @Transactional
        public OaBusinessTripApply audit(BpmnSubmitRequest request) {

            AssertUtil.notEmpty(request.getBizNo(), BizExceptionEnums.PARAM_NOT_NULL, "bizNo");

            OaBusinessTripApply oaBusinessTripApplyOrder = this.getById(OaBusinessTripApply.class, request.getBizNo());

            AssertUtil.notNull(oaBusinessTripApplyOrder, BizExceptionEnums.ORDER_NOT_FOUND);

            List<String> passStatus = Lists.newArrayList(OrderStatusEnums.BpmnStatus.AUDITED.getStatusCode(),
                OrderStatusEnums.BpmnStatus.CLOSED.getStatusCode());

            AssertUtil.notNull(passStatus.contains(request.getBpmnStatus()),BizExceptionEnums.ORDER_AUDIT_STATUS_ERROR);

            //被审批工单允许的状态
            List<String> orderPassStatus = Lists.newArrayList(OrderStatusEnums.BpmnStatus.AUDITING.getStatusCode());

            AssertUtil.isTrue(orderPassStatus.contains(oaBusinessTripApplyOrder.getBpmnStatus()),BizExceptionEnums.ORDER_UNABLE_AUDIT_BY_STATUS,oaBusinessTripApplyOrder.getBpmnStatus());

            if (request.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.AUDITED.getStatusCode())) {
                 oaBusinessTripApplyOrder.setBpmnStatus(OrderStatusEnums.BpmnStatus.AUDITED.getStatusCode());
             }else{
                 oaBusinessTripApplyOrder.setBpmnStatus(OrderStatusEnums.BpmnStatus.CLOSED.getStatusCode());
             }

             this.update(oaBusinessTripApplyOrder);

             return oaBusinessTripApplyOrder;
            }

        private OaBusinessTripApply parseDict(OaBusinessTripApply OaBusinessTripApplyOrder) {
            OaBusinessTripApply cloneOaBusinessTripApply = CloneUtil.deepClone(OaBusinessTripApplyOrder, OaBusinessTripApply.class);
            Result<OaBusinessTripApply> result = Result.OK(cloneOaBusinessTripApply);
            dictService.parseDictResult(result);
            return result.getResult();
        }
}